home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / src / fl_draw_pixmap.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-16  |  7.4 KB  |  269 lines

  1. //
  2. // "$Id: fl_draw_pixmap.cxx,v 1.4.2.3 1999/09/16 05:34:27 bill Exp $"
  3. //
  4. // Pixmap drawing code for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. // Implemented without using the xpm library (which I can't use because
  27. // it interferes with the color cube used by fl_draw_image).
  28. // Current implementation is cheap and slow, and works best on a full-color
  29. // display.  Transparency is not handled, and colors are dithered to
  30. // the color cube.  Color index is achieved by adding the id
  31. // characters together!  Also mallocs a lot of temporary memory!
  32. // Notice that there is no pixmap file interface.  This is on purpose,
  33. // as I want to discourage programs that require support files to work.
  34. // All data needed by a program ui should be compiled in!!!
  35.  
  36. #include <config.h>
  37. #include <FL/Fl.H>
  38. #include <FL/fl_draw.H>
  39. #include <FL/x.H>
  40. #include <ctype.h>
  41. #include <stdio.h>
  42. #include <string.h>
  43.  
  44. static int ncolors, chars_per_pixel;
  45.  
  46. int fl_measure_pixmap(/*const*/char * const *data, int &w, int &h) {
  47.   int i = sscanf(data[0],"%d %d %d %d",&w,&h,&ncolors,&chars_per_pixel);
  48.   if (i<4 || w<=0 || h<=0 ||
  49.       chars_per_pixel!=1 && chars_per_pixel!=2) return w=0;
  50.   return 1;
  51. }
  52.  
  53. #ifdef U64
  54.  
  55. // The callback from fl_draw_image to get a row of data passes this:
  56. struct pixmap_data {
  57.   int w, h;
  58.   const uchar*const* data;
  59.   union {
  60.     U64 colors[256];
  61.     U64* byte1[256];
  62.   };
  63. };
  64.  
  65. // callback for 1 byte per pixel:
  66. static void cb1(void*v, int x, int y, int w, uchar* buf) {
  67.   pixmap_data& d = *(pixmap_data*)v;
  68.   const uchar* p = d.data[y]+x;
  69.   U64* q = (U64*)buf;
  70.   for (int X=(w+1)/2; X--; p += 2) {
  71. #if WORDS_BIGENDIAN
  72.     *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]];
  73. #else
  74.     *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]];
  75. #endif
  76.   }
  77. }
  78.  
  79. // callback for 2 bytes per pixel:
  80. static void cb2(void*v, int x, int y, int w, uchar* buf) {
  81.   pixmap_data& d = *(pixmap_data*)v;
  82.   const uchar* p = d.data[y]+2*x;
  83.   U64* q = (U64*)buf;
  84.   for (int X=(w+1)/2; X--;) {
  85.     U64* colors = d.byte1[*p++];
  86.     int index = *p++;
  87.     U64* colors1 = d.byte1[*p++];
  88.     int index1 = *p++;
  89. #if WORDS_BIGENDIAN
  90.     *q++ = (colors[index]<<32) | colors1[index1];
  91. #else
  92.     *q++ = (colors1[index1]<<32) | colors[index];
  93. #endif
  94.   }
  95. }
  96.  
  97. #else
  98.  
  99. // The callback from fl_draw_image to get a row of data passes this:
  100. struct pixmap_data {
  101.   int w, h;
  102.   const uchar*const* data;
  103.   union {
  104.     U32 colors[256];
  105.     U32* byte1[256];
  106.   };
  107. };
  108.  
  109. // callback for 1 byte per pixel:
  110. static void cb1(void*v, int x, int y, int w, uchar* buf) {
  111.   pixmap_data& d = *(pixmap_data*)v;
  112.   const uchar* p = d.data[y]+x;
  113.   U32* q = (U32*)buf;
  114.   for (int X=w; X--;) *q++ = d.colors[*p++];
  115. }
  116.  
  117. // callback for 2 bytes per pixel:
  118. static void cb2(void*v, int x, int y, int w, uchar* buf) {
  119.   pixmap_data& d = *(pixmap_data*)v;
  120.   const uchar* p = d.data[y]+2*x;
  121.   U32* q = (U32*)buf;
  122.   for (int X=w; X--;) {
  123.     U32* colors = d.byte1[*p++];
  124.     *q++ = colors[*p++];
  125.   }
  126. }
  127.  
  128. #endif
  129.  
  130. #ifdef WIN32
  131. // this is in Fl_arg.C:
  132. extern int fl_parse_color(const char*, uchar&, uchar&, uchar&);
  133. #endif
  134.  
  135. uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
  136.  
  137. int fl_draw_pixmap(/*const*/char*const* di, int x, int y, Fl_Color bg) {
  138.   pixmap_data d;
  139.   if (!fl_measure_pixmap(di, d.w, d.h)) return 0;
  140.   const uchar*const* data = (uchar**)(di+1);
  141.   int transparent_index = -1;
  142.  
  143.   if (ncolors < 0) {    // fltk (non standard) compressed colormap
  144.     ncolors = -ncolors;
  145.     const uchar *p = *data++;
  146.     // if first color is ' ' it is transparent (put it later to make
  147.     // it not be transparent):
  148.     if (*p == ' ') {
  149.       uchar* c = (uchar*)&d.colors[' '];
  150. #ifdef U64
  151.       *(U64*)c = 0;
  152. #if WORDS_BIGENDIAN
  153.       c += 4;
  154. #endif
  155. #endif
  156.       transparent_index = ' ';
  157.       Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
  158.       p += 4;
  159.       ncolors--;
  160.     }
  161.     // read all the rest of the colors:
  162.     for (int i=0; i < ncolors; i++) {
  163.       uchar* c = (uchar*)&d.colors[*p++];
  164. #ifdef U64
  165.       *(U64*)c = 0;
  166. #if WORDS_BIGENDIAN
  167.       c += 4;
  168. #endif
  169. #endif
  170.       *c++ = *p++;
  171.       *c++ = *p++;
  172.       *c++ = *p++;
  173.       *c = 0;
  174.     }
  175.   } else {    // normal XPM colormap with names
  176.     if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1));
  177.     for (int i=0; i<ncolors; i++) {
  178.       const uchar *p = *data++;
  179.       // the first 1 or 2 characters are the color index:
  180.       int index = *p++;
  181.       uchar* c;
  182.       if (chars_per_pixel>1) {
  183. #ifdef U64
  184.     U64* colors = d.byte1[index];
  185.     if (!colors) colors = d.byte1[index] = new U64[256];
  186. #else
  187.     U32* colors = d.byte1[index];
  188.     if (!colors) colors = d.byte1[index] = new U32[256];
  189. #endif
  190.     c = (uchar*)&colors[*p];
  191.     index = (index<<8)+*p++;
  192.       } else {
  193.     c = (uchar *)&d.colors[index];
  194.       }
  195.       // look for "c word", or last word if none:
  196.       const uchar *previous_word = p;
  197.       for (;;) {
  198.     while (*p && isspace(*p)) p++; uchar what = *p++;
  199.     while (*p && !isspace(*p)) p++;
  200.     while (*p && isspace(*p)) p++;
  201.     if (!*p) {p = previous_word; break;}
  202.     if (what == 'c') break;
  203.     previous_word = p;
  204.     while (*p && !isspace(*p)) p++;
  205.       }
  206. #ifdef U64
  207.       *(U64*)c = 0;
  208. #if WORDS_BIGENDIAN
  209.       c += 4;
  210. #endif
  211. #endif
  212. #ifdef WIN32
  213.       if (fl_parse_color((const char*)p, c[0], c[1], c[2])) {;
  214. #else
  215.       XColor x;
  216.       if (XParseColor(fl_display, fl_colormap, (const char*)p, &x)) {
  217.     c[0] = x.red>>8; c[1] = x.green>>8; c[2] = x.blue>>8;
  218. #endif
  219.       } else { // assumme "None" or "#transparent" for any errors
  220.     // this should be transparent...
  221.     Fl::get_color(bg, c[0], c[1], c[2]);
  222.     transparent_index = index;
  223.       }
  224.     }
  225.   }
  226.   d.data = data;
  227.  
  228.   // build the mask bitmap used by Fl_Pixmap:
  229.   if (fl_mask_bitmap && transparent_index >= 0) {
  230.     int W = (d.w+7)/8;
  231.     uchar* bitmap = new uchar[W * d.h];
  232.     *fl_mask_bitmap = bitmap;
  233.     for (int y = 0; y < d.h; y++) {
  234.       const uchar* p = data[y];
  235.       if (chars_per_pixel <= 1) {
  236.     for (int x = 0; x < W; x++) {
  237.       int b = (*p++ != transparent_index);
  238.       if (*p++ != transparent_index) b |= 2;
  239.       if (*p++ != transparent_index) b |= 4;
  240.       if (*p++ != transparent_index) b |= 8;
  241.       if (*p++ != transparent_index) b |= 16;
  242.       if (*p++ != transparent_index) b |= 32;
  243.       if (*p++ != transparent_index) b |= 64;
  244.       if (*p++ != transparent_index) b |= 128;
  245.       *bitmap++ = b;
  246.     }
  247.       } else {
  248.     for (int x = 0; x < W; x++) {
  249.       int b = 0;
  250.       for (int i = 0; i < 8; i++) {
  251.         int index = *p++;
  252.         index = (index<<8) | (*p++);
  253.         if (index != transparent_index) b |= (1<<i);
  254.       }
  255.       *bitmap++ = b;
  256.     }
  257.       }
  258.     }
  259.   }
  260.  
  261.   fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4);
  262.   if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete d.byte1[i];
  263.   return 1;
  264. }
  265.  
  266. //
  267. // End of "$Id: fl_draw_pixmap.cxx,v 1.4.2.3 1999/09/16 05:34:27 bill Exp $".
  268. //
  269.